﻿using Kimd.Common;
using Kimd.Communication;
using Kimd.Logic;
using Kimd.Machine;
using Kimd.Motion;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using WorkStation.Common;

namespace WorkStation.Logic
{
    //名称 轨道拍照1  轨道拍照2
    public class CaptureTrayLogic : FlowBase
    {
        private int _moduleIndex;
        private Tray _feedTray;
        private CommunicationHelper _vision;
        public CaptureTrayLogic(string flowName, FlowManager flowmanager, int moduleIndex)
            : base(flowName, flowmanager)
        {
            this._moduleIndex = moduleIndex;
            _feedTray = new Tray(4, 30);
            if (_moduleIndex == 0)
                _vision = new CommunicationHelper("前模组相机", MachineResource.Instance.MachineTcpClient["前模组相机"]);
            else
                _vision = new CommunicationHelper("后模组相机", MachineResource.Instance.MachineTcpClient["后模组相机"]);
            RegisterDirectSignal("拍照完成");
        }

        public override void Calibrate()
        {
            base.Calibrate();
        }

        public override void Home()
        {
            _vision.EmptySendBuffer();
            if (_moduleIndex == 0)
                GlobalVariable.PCWritePLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCOutFlag>("需上料满Tray")] = false;
            else
                GlobalVariable.PCWritePLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCOutFlag>("需上料满Tray2")] = false;
            _feedTray.Helper.NewEmptyTray();
        }

        public override void Init(out string errInfo)
        {
            base.Init(out errInfo);
        }
        public override void InSingleRunMode()
        {
            if (GlobalVariable.OnSingleRunPause != null)
                GlobalVariable.OnSingleRunPause();
        }
        public override void Method()
        {
            if (!CheckFlowCondition()) return;

            if (GlobalVariable.IsSpotChecking)
                return;
            //向轨道要料
            if (!GlobalVariable.IsDryRun || !SystemConfig.Instance.UsingStatus.IsConveyorSimulate)
            {
                if (!isAllowGet())
                {
                    MachineMessageScheduler.Instance.Add(new MachineMessage(MessageType.Log, $"模组{_moduleIndex + 1}向轨道要入料Tray", this.Description, 0, ""));
                    //先要料
                    if (_moduleIndex == 0)
                        GlobalVariable.PCWritePLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCOutFlag>("需上料满Tray")] = true;
                    else
                        GlobalVariable.PCWritePLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCOutFlag>("需上料满Tray2")] = true;
                }
            }
            else
            {
                Thread.Sleep(500);
            }
            MachineMessageScheduler.Instance.Add(new MachineMessage(MessageType.Log, $"模组{_moduleIndex + 1}等待入料Tray有料信号给出", this.Description, 0, ""));
            //等待上料完成
            while (!isAllowGet() &&
                   !IsBreak() &&
                   !SystemConfig.Instance.UsingStatus.IsConveyorSimulate)
            {
                Thread.Sleep(20);
            }
            Thread.Sleep(500);
            MachineMessageScheduler.Instance.Add(new MachineMessage(MessageType.Log, $"模组{_moduleIndex + 1}复位向轨道要入料Tray信号", this.Description, 0, ""));
            //先要料
            if (_moduleIndex == 0)
                GlobalVariable.PCWritePLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCOutFlag>("需上料满Tray")] = false;
            else
                GlobalVariable.PCWritePLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCOutFlag>("需上料满Tray2")] = false;
            if (!CheckFlowCondition()) return;
            CheckIsClearFunction();
            if (!GlobalVariable.IsDryRun 
                && !SystemConfig.Instance.UsingStatus.IsVisionSimulate 
                && !SystemConfig.Instance.UsingStatus.IsTestTrackEnable)
            {
                (_flowManager.SelectFlow($"Robot{_moduleIndex + 1}模组") as RobotLogic).RobotCommandRun("GoCapture", "机器人去拍Tray点位失败", out string recvStr2);
                if (!CheckFlowCondition()) return;
                MachineMessageScheduler.Instance.Add(new MachineMessage(MessageType.Log, $"模组{_moduleIndex + 1}收到入料Tray来料信号", this.Description, 0, ""));
            recapture:
                DateTime dateTime = DateTime.Now;
                SendPackage sp = new SendPackage();
                sp.Message = "CaptureTray";
                TcpClientSendAndReceive(_vision, sp, 200000, 3, out string recvStr);
                if (string.IsNullOrEmpty(recvStr))
                {
                    MachineMessageScheduler.Instance.Add(new MachineMessage(MessageType.Warn, $"{_vision.Description}接收超时", this.Description, 9, "系统"));
                    if (!CheckFlowCondition()) return;
                    goto recapture;
                }
                TimeSpan ts = DateTime.Now - dateTime;
                LogHelper.Instance.Log(this.Description, $"相机拍Tray: {ts.Milliseconds}ms", MessageLevel.CT);

                List<bool> sts = new List<bool>();
                if (string.IsNullOrEmpty(recvStr) || recvStr.Contains("NG"))
                {
                    ShowWarnAndPause("视觉回复NG", "系统");
                    if (!CheckFlowCondition()) return;
                    goto recapture;
                }
                else if (recvStr.Contains("OK"))
                {
                    sts = recvStr.Split(',').Skip(2).Take(recvStr.Split(',').Length - 2).Select(s => s == "1").ToList();
                }
                else
                {
                    ShowWarnAndPause("视觉拍上料Tray盘回复异常", $"机器人{_moduleIndex + 1}模组");
                    _vision.AddPackage(sp);
                    if (!CheckFlowCondition()) return;
                }
                if (!CheckFlowCondition()) return;
                //根据视觉结果确定料有无
                _feedTray.Helper.NewFullTray();
                if (!SystemConfig.Instance.UsingStatus.DefaultCCDIsFullEnable)
                {
                    for (int i = 0; i < 120; i++)
                    {
                        _feedTray.Helper.SetCellStatus(i, sts[i] ? CellStatus.HasProduct : CellStatus.NoProduct);
                    }
                    if (_feedTray.Helper.Count(c => c.Status == CellStatus.HasProduct) != 120)
                    {
                        ShowWarnAndPause("视觉未检测到满盘", "系统");
                        if (MessageBox.Show("是否继续?点击 是 继续，点击 否 重新识别", "视觉", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                        {
                            goto recapture;
                        }
                    }
                    else if (_feedTray.Helper.Count(c => c.Status == CellStatus.HasProduct) % 2 != 0)
                    {
                        ShowWarnAndPause("视觉检测到奇数料", "系统");
                        if (MessageBox.Show("是否继续?点击 是 继续，点击 否 重新识别", "视觉", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                        {
                            goto recapture;
                        }
                    }
                }
            }
            else
            {
                Thread.Sleep(500);
                _feedTray.Helper.NewFullTray();
                if (GlobalVariable.IsGrrMode || GlobalVariable.IsCosmeticMode)
                {
                    for (int i = 0; i < 120; i++)
                    {
                        if (i == 0)
                            _feedTray.Helper.SetCellStatus(i, CellStatus.HasProduct);
                        else if (i == 60)
                            _feedTray.Helper.SetCellStatus(i, CellStatus.HasProduct);
                        else if (i == 1)
                            _feedTray.Helper.SetCellStatus(i, CellStatus.HasProduct);
                        else if (i == 61)
                            _feedTray.Helper.SetCellStatus(i, CellStatus.HasProduct);
                        else if (i == 2)
                            _feedTray.Helper.SetCellStatus(i, CellStatus.HasProduct);
                        else if (i == 62)
                            _feedTray.Helper.SetCellStatus(i, CellStatus.HasProduct);
                        //else if (i == 3)
                        //    _feedTray.Helper.SetCellStatus(i, CellStatus.HasProduct);
                        //else if (i == 15)
                        //    _feedTray.Helper.SetCellStatus(i, CellStatus.HasProduct);
                        //else if (i == 75)
                        //    _feedTray.Helper.SetCellStatus(i, CellStatus.HasProduct);
                        //else if (i == 20)
                        //    _feedTray.Helper.SetCellStatus(i, CellStatus.HasProduct);
                        else
                            _feedTray.Helper.SetCellStatus(i, CellStatus.NoProduct);
                    }
                }
            }
            if (!CheckFlowCondition()) return;
            if (!SystemConfig.Instance.UsingStatus.IsTestTrackEnable)
            {
                if (_moduleIndex == 0 && !SystemConfig.Instance.UsingStatus.IsRobot1Disable)
                    //上料拍照引导
                    (_flowManager.SelectFlow($"Robot{_moduleIndex + 1}模组") as RobotLogic).CaptureFeedTray();
                if (_moduleIndex == 1 && !SystemConfig.Instance.UsingStatus.IsRobot2Disable)
                    //上料拍照引导
                    (_flowManager.SelectFlow($"Robot{_moduleIndex + 1}模组") as RobotLogic).CaptureFeedTray();
                if (!CheckFlowCondition()) return;

                SetSignal("拍照完成");

                WaitForSignal($"Robot{_moduleIndex + 1}模组", "料取完");
            }
            else
            {
                MachineMessageScheduler.Instance.Add(new MachineMessage(MessageType.Log, $"测试流道{_moduleIndex + 1}", this.Description, 0, ""));
                Thread.Sleep(5000);
            }
            if (!CheckFlowCondition()) return;
            if (_moduleIndex == 0)
            {
                MachineMessageScheduler.Instance.Add(new MachineMessage(MessageType.Log, $"前模组告诉轨道取上料满Tray完成", this.Description, 0, ""));
                GlobalVariable.PCWritePLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCOutFlag>("取上料满Tray完成")] = true;
                Thread.Sleep(500);
                //等待下空tray完成
                while (!isEmptyTrayUnloadFinish() && !IsBreak() && !SystemConfig.Instance.UsingStatus.IsConveyorSimulate)
                {
                    Thread.Sleep(20);
                }
                if (!CheckFlowCondition()) return;
                MachineMessageScheduler.Instance.Add(new MachineMessage(MessageType.Log, $"前模组复位告诉轨道取上料满Tray完成", this.Description, 0, ""));
                GlobalVariable.PCWritePLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCOutFlag>("取上料满Tray完成")] = false;
            }
            else
            {
                MachineMessageScheduler.Instance.Add(new MachineMessage(MessageType.Log, $"后模组复位告诉轨道取上料满Tray完成", this.Description, 0, ""));
                GlobalVariable.PCWritePLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCOutFlag>("取上料满Tray完成2")] = true;
                Thread.Sleep(500);
                //等待下空tray完成
                while (!isEmptyTrayUnloadFinish() && !IsBreak() && !SystemConfig.Instance.UsingStatus.IsConveyorSimulate)
                {
                    Thread.Sleep(20);
                }
                if (!CheckFlowCondition()) return;
                MachineMessageScheduler.Instance.Add(new MachineMessage(MessageType.Log, $"后模组复位告诉轨道取上料满Tray完成", this.Description, 0, ""));
                GlobalVariable.PCWritePLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCOutFlag>("取上料满Tray完成2")] = false;
            }
            if (!CheckFlowCondition()) return;
            //清料且清空一盘的情况下，等待清料结束才再要料
            CheckIsClearFunction();
            if (!CheckFlowCondition()) return;
        }

        public void CheckIsClearFunction()
        {
            if (_moduleIndex == 0)
            {
                while ((GlobalVariable.IsClearLater || GlobalVariable.IsClearNow) && !IsBreak())
                {
                    Thread.Sleep(20);
                }
            }
            else
            {
                while ((GlobalVariable.IsClearLater2 || GlobalVariable.IsClearNow2) && !IsBreak())
                {
                    Thread.Sleep(20);
                }
            }
        }

        public override void OnStop()
        {
            base.OnStop();
        }

        public override bool PreStartCheck()
        {
            return base.PreStartCheck();
        }
        public Tray GetFeedTray()
        {
            return _feedTray;
        }
        private bool isAllowGet()
        {
            if (_moduleIndex == 0)
                return GlobalVariable.PCReadPLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCInFlag>("允许取上料满Tray")];
            else
                return GlobalVariable.PCReadPLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCInFlag>("允许取上料满Tray2")];
        }
        private bool isEmptyTrayUnloadFinish()
        {
            if (_moduleIndex == 0)
                return GlobalVariable.PCReadPLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCInFlag>("下空Tray完成")];
            else
                return GlobalVariable.PCReadPLCData[(int)EnumHelper.GetEnumValueFromDescription<PLCInFlag>("下空Tray完成2")];
        }
        public CommunicationHelper GetVision()
        {
            return _vision;
        }
    }
}
